/*
** Copyright (c) 2008 Mobile GCalendarManager
**
** Permission is hereby granted, free of charge, to any person
** obtaining a copy of this software and associated documentation
** files (the "Software"), to deal in the Software without
** restriction, including without limitation the rights to use,
** copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the
** Software is furnished to do so, subject to the following
** conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
** OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
** HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
** OTHER DEALINGS IN THE SOFTWARE.
*/

package au.edu.mq.comp.itec800.mgc.util;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;

import au.edu.mq.comp.itec800.mgc.MGC;

/**
 * Command-Line options management class.
 *
 * @author Andrey Chislenko [andrey.chislenko@students.mq.edu.au]
 */
public class OptionParser
{
  private static final String[][] DEFINITIONS =
  {
    // opt longopt value? required? description
    { "b", "batch",   null, null, "batch mode"                                },
    { "h", "help",    null, null, "print this message"                        },
    { "v", "version", null, null, "version information"                       },
    { "i", "ui",      "t",  null, "user interface selection (CLI / GUI)"      },
    { "l", "login",   "t",  null, "auto authentication (username[:password])" }
  };
  private static final String     SYNOPSYS    = "\n"
      + "mgc [-bil] [--batch] [--login=username[:password]] [--ui={cli|gui}] [query...]\n"
      + "mgc [--hv] [--help] [--version]";
  private static final String     HEADER      = "\n\nOPTIONS:\n\n";
  private static final String     FOOTER      = "\n\n";

  private Options                 options     = null;


  public OptionParser()
  {
    parse(new String[0]);
  }

  public OptionParser(final String[] args)
  {
    parse(args);
  }

  private Options getOptions()
  {
    if (options == null)
    {
      options = new Options();

      for (final String[] o : DEFINITIONS)
      {
        if (o != null)
        {
          final Option option = new Option(o[0], o[1], o[2] != null, o[4]);

          if (o[2] != null)
          {
            option.setValueSeparator('=');
          }
          if (o[3] != null)
          {
            option.setRequired(true);
          }
          options.addOption(option);
        }
      }
    }
    return (options);
  }

  private void printHelp()
  {
    final HelpFormatter formatter = new HelpFormatter();

    formatter.setLeftPadding(3);
    formatter.printHelp(SYNOPSYS, HEADER, getOptions(), FOOTER);
  }

  public void               parse(final String[] args)
  {
    final CommandLineParser parser = new PosixParser();

    try
    {
      final CommandLine   line    = parser.parse(getOptions(), args);
      final Configuration config  = MGC.getInstance().getConfiguration();
      final String[]      queries = line.getArgs();

      if (line.hasOption("help"))
      {
        printHelp();
        System.exit(0);
      }
      if (line.hasOption("version"))
      {
        System.out.println(MGC.version());
        System.exit(0);
      }
      if (line.hasOption("batch"))
      {
        config.setProperty("batch", "true");
      }
      if (line.hasOption("login"))
      {
        final String    value   = StringUtils.clean(line.getOptionValue("login"));
        final String[]  tokens  = value.split(":", 2);
        final String    user    = StringUtils.getValidArg(tokens, 0).trim();
        final String    pass    = StringUtils.getValidArg(tokens, 1).trim();

        // in all cases, we want to have default values removed
        config.remove("user");
        config.remove("password");
        if (user.length() > 0)
        {
          config.setProperty("user", user);
          if (pass.length() > 1)
          {
            config.setProperty("password", pass);
          }
        }
      }
      if (line.hasOption("ui"))
      {
        final String  value = StringUtils.clean(line.getOptionValue("ui"));

        if ("cli".equalsIgnoreCase(value) || "gui".equalsIgnoreCase(value))
        {
          config.setProperty("ui", value);
        }
      }
      if ((queries != null) && (queries.length > 0))
      {
        config.setArguments(queries);
      }
    }
    catch (final ParseException exp)
    {
      printHelp();
      System.exit(-1);
    }
  }
}
